package com.birdboot.core;

import com.birdboot.annotations.Controller;
import com.birdboot.annotations.RequestMapping;
import com.birdboot.controller.UserController;
import com.birdboot.http.HttpServletRequest;
import com.birdboot.http.HttpServletResponse;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;

/*
* V8新增内容;
* 该类是SpringMVC框架与Tomcat整合时的一个关键类
* Tomcat处理业务原生的都是调用继承了HttpServlet的类来完成，此时需要进行很多配置
* 以及使用时要做很多重复性劳动
* SpringMVC框架提供的该类也继承了HttpServlet的，使用它来接收处理请求的工作
* */
public class DispatcherServlet {
    private static File baseDir; //类加载路径
    private static File staticDir;//类加载路径中的static目录
    static {
        //定位当前项目的类加载路径
        try {
            baseDir = new File(
                    DispatcherServlet.class.getClassLoader().getResource(".").toURI()
            );
            //定位类加载路径下的static目录
            staticDir = new File(baseDir,"static");
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }
    /*
    * service方法实际上是当我们继承了HttpServlet后必须重写的方法
    * 该方法要求接收两个参数：请求对象与响应对象
    * Tomcat在处理请求时就是调用某个Servlet的service方法并将请求与响应对象传入来让其完成处理工作的
    * */
    public void service(HttpServletRequest request, HttpServletResponse response) {
        //获取请求的抽象路径
        //不能再使用uri判断请求了，因为uri可能含有参数，内容不固定
        String path = request.getRequestURI();
        System.out.println(path);
        /*
        * v17新增内容
        * 当我们得到本次请求路径path的值后，我们首先要查看是否为请求业务
        * 1：扫描controller包下的所有类
        * 2：查看哪些被注解@Controller标注过的类(只有被该注解标注过的类才认可为业务处理类)
        * 3：便利这些类，并获取他们的所有方法，并查看哪些是业务方法
        * 只有被注解@RequestMapping标注的方法才是业务方法
        * 4：遍历业务方法时比对该方法上@RequestMapping中传递的参数值是否与本次请求路径path值一致？如果一致则说明本次请求就应当由该方法进行处理，因此利用反射机调用该方法进行处理。
        * 提示：反射机制调用后要记得return，避免执行后续处理静态资源
        * 5：如果扫描了所有的Controller中所有方法，均未找到与本次请求匹配的路径
        * 则说明本次请求并非处理业务，那么执行下面请求静态资源的操作
        * */
        Method method = HandlerMapping.getMethod(path);
//        System.out.println("methodmethodmethodmethodmethodmethod"+method);
        if(method!=null){ //本次为请求业务
            try {
                //通过方法获取其所属类的类对象(某个Controller)
                Class cls = method.getDeclaringClass();
                Object obj = cls.newInstance();
                method.invoke(obj,request,response);
            } catch (Exception e) {
                //如果处理业务过程中报错，这是典型的因为服务端处理请求出现错误导致处理失败(500错误)
                response.setStatusCode(500);
                response.setStatusReason("Internal Server Error");
            }
        }else {
            File file = new File(staticDir, path);
            if (file.isFile()) {
                //由于响应对象中状态代码和描述默认值是200，OK因此正确情况下不用再设置
                response.setContentFile(file);
                response.addHeader("Server", "BirdServer");
            } else {
                response.setStatusCode(404);
                response.setStatusReason("NotFound");
                file = new File(staticDir, "404.html");
                response.setContentFile(file);
                response.addHeader("Server", "BirdServer");
            }
        }
    }
}
